/* $URL$
   $Rev$
   $Author$
   $Date$
   $Id$
 */

 // #define USE_GL3W
#include <vermilion.h>
#include "vapp.h"
#include "vutils.h"
#include "vbm.h"
#include "vmath.h"
#include "LoadShaders.h"
#include <stdio.h>

BEGIN_APP_DECLARATION(LightingExample)
// Override functions from base class
virtual void Initialize(const char* title);
virtual void Display(bool auto_redraw);
virtual void Finalize(void);
virtual void Reshape(int width, int height);

// Texture for compute shader to write into
GLuint output_image;

// Program, vao and vbo to render a full screen quad
GLuint render_prog;

// Uniform locations
GLint mv_mat_loc;
GLint prj_mat_loc;
GLint col_amb_loc;
GLint col_diff_loc;
GLint col_spec_loc;

// Object to render
VBObject    object;
END_APP_DECLARATION()

DEFINE_APP(LightingExample, "Lighting Example")

void LightingExample::Initialize(const char* title)
{
	base::Initialize(title);

	static ShaderInfo shader_info[] =
	{
		{ GL_VERTEX_SHADER,   "light_models.vs.glsl" },
		{ GL_FRAGMENT_SHADER, "light_models.fs.glsl" },
		{ GL_NONE, NULL }
	};

	render_prog = LoadShaders(shader_info);

	glUseProgram(render_prog);

	mv_mat_loc = glGetUniformLocation(render_prog, "model_matrix");
	prj_mat_loc = glGetUniformLocation(render_prog, "proj_matrix");
	col_amb_loc = glGetUniformLocation(render_prog, "color_ambient");
	col_diff_loc = glGetUniformLocation(render_prog, "color_diffuse");
	col_spec_loc = glGetUniformLocation(render_prog, "color_specular");

	object.LoadFromVBM("../../../media/unit_torus.vbm", 0, 1, 2);
}

void LightingExample::Display(bool auto_redraw)
{
	//float time = 0.5f; 
	float time = float(GetTickCount() & 0xFFFF) / float(0xFFFF);

	vmath::mat4 mv_matrix = vmath::translate(0.0f, 0.0f, -4.0f) *
		vmath::rotate(987.0f * time * 3.14159f, vmath::vec3(0.0f, 0.0f, 1.0f)) *
		vmath::rotate(1234.0f * time * 3.14159f, vmath::vec3(1.0f, 0.0f, 0.0f));
	vmath::mat4 prj_matrix = vmath::perspective(60.0f, 1.333f, 0.1f, 1000.0f);

	glUseProgram(render_prog);

	glUniformMatrix4fv(mv_mat_loc, 1, GL_FALSE, mv_matrix);
	glUniformMatrix4fv(prj_mat_loc, 1, GL_FALSE, prj_matrix);

	// Clear, select the rendering program and draw a full screen quad
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glCullFace(GL_BACK);
	glEnable(GL_CULL_FACE);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	object.Render();

	base::Display();
}

void LightingExample::Finalize(void)
{
	glUseProgram(0);
	glDeleteProgram(render_prog);
	glDeleteTextures(1, &output_image);
}

void LightingExample::Reshape(int width, int height)
{
	glViewport(0, 0, width, height);
}
